<template>
  <div id="FormPlus">
    <el-form
      ref="ruleFormRef"
      :rules="rules"
      :inline="inline"
      :model="ruleForm"
      class="ruleForm"
      :label-width="labelWidth"
      :style="formStyle"
    >
      <div class="formBox">
        <template v-for="(item, index) in list">
          <template v-if="!item.type || item.type === 'input'">
            <el-form-item
              :key="index"
              :label="item.label"
              :prop="item.model"
              :required="item.required"
            >
              <el-input
                v-model.trim="ruleForm[item.model]"
                :clearable="item.clearable"
                filterable
                :placeholder="item.placeholder"
              />
            </el-form-item>
          </template>
          <template v-if="item.type === 'select'">
            <el-form-item
              :key="index"
              :label="item.label"
              :prop="item.model"
              :required="item.required"
            >
              <el-select
                :style="`width: ${formItemContentWidth}`"
                v-model.trim="ruleForm[item.model]"
                :clearable="item.clearable === undefined || item.clearable"
                filterable
                :placeholder="item.placeholder || ''"
                @change="item.isSelectChange ? submitForm(ruleFormRef) : ''"
              >
                <el-option
                  v-for="itemSon in item.options"
                  :key="itemSon.value"
                  :label="itemSon.label"
                  :value="itemSon.value"
                >
                </el-option>
              </el-select>
            </el-form-item>
          </template>
          <template v-if="item.type === 'date-picker'">
            <el-form-item
              :key="index"
              :prop="item.model"
              :label="item.label"
              :required="item.required"
            >
              <el-date-picker
                :style="`width: ${formItemContentWidth}`"
                v-model.trim="ruleForm[item.model]"
                :clearable="item.clearable === undefined || item.clearable"
                :type="item.pickerType"
                :placeholder="item.placeholder"
                :format="item.format"
                :value-format="item.valueFormat"
                :shortcuts="item.shortcuts"
              />
            </el-form-item>
          </template>
          <template v-if="item.type === 'datetimerange'">
            <el-form-item
              :key="index"
              :prop="item.model"
              :label="item.label"
              :required="item.required"
            >
              <el-date-picker
                v-model.trim="ruleForm[item.model]"
                type="datetimerange"
                :format="item.format"
                :value-format="item.valueFormat"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
              >
              </el-date-picker>
            </el-form-item>
          </template>
          <template v-if="item.type === 'radio'">
            <el-form-item
              :key="index"
              :prop="item.model"
              :label="item.label"
              :required="item.required"
            >
              <el-radio-group v-model="ruleForm[item.model]">
                <el-radio
                  v-for="(itemRadio, index) in item.itemRadioList"
                  :key="index"
                  :label="itemRadio"
                  :border="item.borderHideOrShow"
                ></el-radio>
              </el-radio-group>
            </el-form-item>
          </template>
        </template>
      </div>
      <div v-show="flagHideOrUnfoldLocal">
        <slot></slot>
      </div>
    </el-form>
    <el-row>
      <el-col class="btn-container">
        <el-button
          :icon="Search"
          type="primary"
          @click="submitForm(ruleFormRef)"
          >查询</el-button
        >
        <el-button
          v-if="resList"
          :icon="Reading"
          type="primary"
          @click="advancedQuery"
          >高级查询</el-button
        >
        <el-button :icon="RefreshRight" @click="resetForm(ruleFormRef)"
          >重置</el-button
        >
        <el-button
          v-if="!flagShowHide"
          :icon="flagHideOrUnfoldLocal ? ArrowDown : ArrowUp"
          @click="flagLocal"
          >{{ flagHideOrUnfoldLocal ? "展开" : "收起" }}</el-button
        >
      </el-col>
    </el-row>
  </div>
  <!-- 高级查询模态框 -->
  <el-dialog
    v-model="dialogVisible"
    title="高级查询弹框"
    width="60%"
    draggable
    class="unity_advancedQueryDialog"
  >
    <el-card class="box-card" style="margin: 0">
      <template #header>
        <div class="card-header">
          <span>高级查询</span>
        </div>
      </template>
      <el-row>
        <!-- 左侧搜索 -->
        <el-col :span="18">
          <el-form
            v-if="formAdvanced.configList.multiConditionList.length > 0"
            :model="formAdvanced.configList"
            label-width="120px"
          >
            <el-form-item label="过滤条件匹配:">
              <el-select
                v-model="formAdvanced.configList.filterCondition"
                style="width: 100%"
              >
                <el-option label="AND 所有条件都要求匹配" value="and" />
                <el-option label="OR 条件中的任意一个匹配" value="or" />
              </el-select>
            </el-form-item>
            <el-form-item
              v-for="(item, index) in formAdvanced.configList
                .multiConditionList"
              :key="index"
            >
              <div class="box-search">
                <div class="search-item">
                  <el-select
                    v-model="item.fieldsName"
                    placeholder="选择查询字段"
                    clearable
                    filterable
                    style="margin-right: 10px; flex: 4"
                  >
                    <el-option
                      v-for="itemSon in option.optList"
                      :key="itemSon.fieldCode"
                      :label="itemSon.fieldName"
                      :value="itemSon.fieldCode"
                    />
                  </el-select>
                  <el-select
                    style="margin-right: 10px; flex: 2"
                    v-model="item.operator"
                  >
                    <el-option
                      v-for="itemS in item.matchingTypeList"
                      :key="itemS.value"
                      :label="itemS.label"
                      :value="itemS.value"
                    />
                  </el-select>
                  <el-input
                    style="margin-left: 10px; flex: 4"
                    v-model="item.content"
                    placeholder="请输入值"
                  ></el-input>
                </div>
                <div class="iconList">
                  <el-button :icon="Plus" circle @click="addItem" />
                  <el-button
                    :icon="Minus"
                    circle
                    @click="deleteItem(item.id)"
                  />
                </div>
              </div>
            </el-form-item>
          </el-form>
          <el-empty style="height: 150px" :image-size="120" v-else>
            <template #description>
              <div>
                <span> 没有任何查询条件 </span>
                <el-divider direction="vertical" border-style="dashed" />
                <span class="modality" @click="resetSearchCondition">
                  点击新增
                </span>
              </div>
            </template>
          </el-empty>
        </el-col>
        <!-- 右侧保存查询树 -->
        <el-col :span="6">
          <el-card class="saveSearch">
            <template #header>
              <div>保存的查询</div>
            </template>
            <el-tree
              ref="tree"
              class="my-tree"
              :data="treeList.list"
              :expand-on-click-node="false"
              node-key="id"
              accordion
              highlight-current
              @node-click="handleNodeClick"
            >
              <template #default="{ node, data }">
                <div class="custom-tree-node">
                  <div>{{ node.label }}</div>
                  <div style="margin-right: 12px">
                    <el-icon @click.stop="removeTreeItem(node, data)">
                      <Close />
                    </el-icon>
                  </div>
                </div>
              </template>
            </el-tree>
          </el-card>
        </el-col>
      </el-row>
    </el-card>

    <template #footer>
      <div class="dialog-footer-advanced">
        <div>
          <el-button @click="resetSearchCondition">重置</el-button>
          <el-button @click="saveSearchCondition">保存查询条件</el-button>
        </div>
        <div>
          <el-button @click="dialogVisible = false">关闭</el-button>
          <el-button type="primary" @click="selectList"> 查询 </el-button>
        </div>
      </div>
    </template>
  </el-dialog>
</template>

<script lang="ts" setup>
import { reactive, ref, inject, computed, onMounted } from "vue";
import {
  Search,
  RefreshRight,
  ArrowUp,
  ArrowDown,
  Reading,
  Plus,
  Minus,
  Close,
} from "@element-plus/icons-vue";
import type { FormInstance } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { getAction, postAction, deleteAction } from "@/utils/system/commonUse";

export interface options {
  value: string;
  label: string;
}

export interface FormProps {
  // 表单类型
  type?: string;
  // 表单名
  label: string;
  // 绑定的字段
  model: string;
  // 是否必填
  required?: Boolean;
  // 输入框  是否有清空
  clearable?: Boolean;
  // 提示
  placeholder?: string;
  // 下拉框的 选项
  options?: Array<options>;
  // 时间选项
  pickerType?: string;
  // 时间选项的 格式自定义
  format?: string;
  // 获取出来的值得格式
  valueFormat?: string;
  // 判断下拉框是否需要下拉事件
  isSelectChange?: boolean;
  // 快捷选择日期
  shortcuts?: Array<{
    text: string;
    value: Function | string | Date;
  }>;
}

// 接受props
const props = defineProps({
  rules: {
    type: Object,
    default: () => {},
  },
  formItemContentWidth: {
    type: String,
    default: "165px",
  },
  list: {
    type: Array as any,
    default: () => [],
  },
  inline: {
    type: Boolean,
    default: true,
  },
  labelWidth: {
    type: String,
    default: "70px",
  },
  // 是否需要展开收缩
  flagHideOrUnfold: {
    type: Boolean,
    default: false,
  },
  //  表单的默认值
  defaultValue: {
    type: Object,
    default: {},
  },
  // 表格编码
  tableCode: {
    type: String,
    default: "",
  },
  // 控制显示隐藏
  flagShowHide: {
    type: Boolean,
    default: true,
  },
  // 高级搜索列表
  // treeList: {
  //   type: Array,
  //   default: [],
  // },
});
// 表单默认值
const defaultValueLocal = props.defaultValue;

// 取数 是否展开收缩
const flagHideOrUnfoldLocal = ref(props.flagHideOrUnfold);
const flagLocal = () => {
  flagHideOrUnfoldLocal.value = !flagHideOrUnfoldLocal.value;
};
// ref 表单实例
const ruleFormRef = ref<FormInstance>();
// 自定义事件
const emit = defineEmits(["submitForm", "resetForm", "getSearchList"]);
// 表单数据
const ruleForm: any = reactive({});

// 加载前
onMounted(() => {
  for (const key in defaultValueLocal) {
    ruleForm[key] = JSON.parse(JSON.stringify(defaultValueLocal[key]));
  }
});

const formStyle = computed(() => {
  return {
    "--formItemContentWidth": props.formItemContentWidth,
  };
});
// 所填写数据
const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.validate((valid) => {
    if (!valid) {
      return;
    }
    const exportData = { ...ruleForm };
    emit("submitForm", exportData);
  });
};
// 默认清空所填写数据
const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.resetFields();
  emit("resetForm");
};
// ================================================高级查询==============================================================
// 控制弹框
let dialogVisible = ref(false);
const option = reactive({
  optList: <
    | [
        {
          dictCode: string;
          fieldCode: string;
          fieldName: string;
          fieldType: string;
        }
      ]
    | null
  >null,
});
// 保存的搜索项
const treeList = reactive({
  list: [],
});
// 高级搜索条件
const condition = [
  {
    value: "=",
    label: "等于",
  },
  {
    value: ">",
    label: "大于",
  },
  {
    value: "<",
    label: "大于",
  },
  {
    value: "like",
    label: "包含",
  },
];
// 注入祖先组件放下来的 获取高级搜索列表方法
// const resList = inject("getSearchList", undefined) as Function;
let resList = inject("getAdvancedQueryList", undefined);
let getSaveList = inject("getSaveList", () => {}) as Function;
// 高级查询 过滤条件
const formAdvanced = reactive({
  configList: {
    filterCondition: "and",
    tableCode: props.tableCode,
    label: "",
    multiConditionList: [
      {
        id: Math.random() * 180 + 60,
        fieldsName: "",
        operator: "=",
        matchingTypeList: condition,
        // 值
        content: "",
      },
    ],
  },
});
/**
 * 单击高级查询
 */
const advancedQuery = async () => {
  // console.log("resList==》单击高级查询", resList);
  // 代表祖先组件未曾发布事件
  if (resList == undefined) {
    return;
  }
  // 获取高级搜索下拉字段
  const fun = resList as Function;
  let res = await fun();
  option.optList = res;
  // 获取高级搜索保存列表
  let saveListRes = await getSaveList();
  treeList.list = saveListRes;
  console.log("saveListRes", saveListRes);

  dialogVisible.value = true;
};
const url = reactive({
  getDetailseList: "/dynamic/queryInfo/getById",
  saveDetailseList: "/dynamic/queryInfo/save",
  delDetailseList: "/dynamic/queryInfo/delete",
});
/**
 * 单击高级查询树
 */
const handleNodeClick = (data: any) => {
  getAction(`${url.getDetailseList}/${data.id}`)
    .then((data: any) => {
      if (data.code != 1000) {
        return ElMessage.error(data.msg);
      }
      formAdvanced.configList = data.data;
      formAdvanced.configList.tableCode = props.tableCode;
      formAdvanced.configList.label = "";
    })
    .catch((err) => {
      ElMessage.error("获取搜索详情失败");
    });
};
/**
 * 保存高级查询条件
 */
const saveSearchCondition = () => {
  for (const item in formAdvanced.configList.multiConditionList) {
    if (
      formAdvanced.configList.multiConditionList[item].content == "" ||
      formAdvanced.configList.multiConditionList[item].fieldsName == ""
    ) {
      return ElMessage.warning("空条件不能保存");
    }
  }
  ElMessageBox.prompt("请填写保存的名字", "填写", {
    confirmButtonText: "确认",
    cancelButtonText: "取消",
    inputPattern: /^.+$/,
    inputErrorMessage: "不能为空",
  })
    .then(({ value }) => {
      formAdvanced.configList.label = value;
      postAction(url.saveDetailseList, formAdvanced.configList)
        .then((data: any) => {
          if (data.code == "1000") {
            getSaveList()
              .then((result: any) => {
                treeList.list = result;
              })
              .catch((errDetail: any) => {
                ElMessage.error("获取保存列表失败");
              });
          }
        })
        .catch((err) => {
          console.log("err", err);
          ElMessage.error("保存失败");
        });
    })
    .catch(() => {
      ElMessage({
        type: "info",
        message: "取消",
      });
    });
};
/**
 * 删除保存的列表 （单一）
 */
const removeTreeItem = (node: any, data: any) => {
  console.log("node", node);
  console.log("data", data);
  deleteAction(`${url.delDetailseList}/${data.id}`)
    .then((res: any) => {
      console.log("res", res);
      if (res.code == "1000") {
        getSaveList()
          .then((result: any) => {
            treeList.list = result;
          })
          .catch((errDetail: any) => {
            ElMessage.error("获取保存列表失败");
          });
        return ElMessage.success(res.msg);
      }
    })
    .catch((err: any) => {
      console.log("err", err);
      ElMessage.error("删除失败");
    });
};
/**
 * 重置 | 点击新增
 */
const resetSearchCondition = () => {
  formAdvanced.configList = {
    filterCondition: "and",
    tableCode: props.tableCode,
    label: "",
    multiConditionList: [
      {
        id: Math.random() * 180 + 60,
        fieldsName: "",
        operator: "=",
        matchingTypeList: condition,
        // 值
        content: "",
      },
    ],
  };
};

/**
 * 删除其中一个搜索项
 */
const deleteItem = (idx: number) => {
  // 根据行内项 删除
  formAdvanced.configList.multiConditionList =
    formAdvanced.configList.multiConditionList.filter((item) => {
      return item.id != idx;
    });
};

/**
 * 添加高级搜索项
 */
const addItem = () => {
  formAdvanced.configList.multiConditionList.push({
    id: Math.random() * 1000 + 60,
    fieldsName: "",
    operator: "=",
    matchingTypeList: condition,
    // 值
    content: "",
  });
};

/**
 * 确认查询列表
 * */
const selectList = () => {
  emit(
    "getSearchList",
    formAdvanced.configList.multiConditionList,
    formAdvanced.configList.filterCondition
  );
};
</script>

<style lang="scss" scoped>
#FormPlus {
  .ruleForm {
    width: 100%;
    .formBox {
      display: flex;
      flex-wrap: wrap;
      flex-direction: row;
      ::v-deep.el-form-item__content {
        width: var(--formItemContentWidth);
      }
      ::v-deep.el-form-item__content .el-date-editor,
      .el-input {
        width: var(--formItemContentWidth);
      }
    }
  }
  .btn-container {
    display: flex;
    justify-content: flex-end;
  }
}
::v-deep.el-form--inline .el-form-item {
  // display: inline-flex;
  // vertical-align: middle;
  margin-right: 0px;
  // flex-direction: row;
  // flex-wrap: wrap;
  // align-items: center;
}
.iconList {
  display: flex;
  justify-content: flex-end;
  margin-left: 10px;
}
.saveSearch {
  margin: 0 0 0 6px;
  :deep(.el-card__header) {
    padding: 10px;
    font-size: 14px;
  }
  :deep(.el-card__body) {
    padding: 2px 0;
  }
}
//=============================================== 高级弹框 =============================================

.dialog-footer-advanced {
  display: flex;
  justify-content: space-between;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
.box-search {
  display: flex;
  .search-item {
    display: flex;
  }
}
</style>
<!-- 为何使用两个style 因为想自定义header下侧横线  具体查看此文章 https://blog.csdn.net/qq_32154641/article/details/126708678-->
<style lang="scss">
.unity_advancedQueryDialog {
  .el-dialog__header {
    margin-right: 0;
    border-bottom: 1px solid #e8e8e8;
    border-radius: 4px 4px 0 0;
    color: rgba(0, 0, 0, 0.65);
    background: #fff;
  }
  .el-dialog__footer {
    border-top: 1px solid #e8e8e8;
    .dialog-footer-advanced {
      padding-top: 6px;
    }
  }
}
.my-tree {
  :deep(.el-tree-node__content) {
    height: 36px;
  }
  :deep(.el-tree-node.is-current > .el-tree-node__content) {
    background-color: rgba(64, 158, 255, 0.4);
  }
  :deep(.el-tree-node > .el-tree-node__content) {
    transition: 0.2s;
  }
  .custom-tree-node {
    flex: 1;
    display: flex;
    justify-content: space-between;
  }
}
.modality {
  cursor: pointer;
  color: #1890ff;
}
</style>
